home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dme / cmd2.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  25KB  |  1,266 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  * CMD2.C
  9.  */
  10.  
  11. #include "defs.h"
  12. #include <workbench/startup.h>
  13. #include <workbench/workbench.h>
  14.  
  15. Prototype struct _ED *uninit_init (struct _ED *);
  16. Prototype void do_remeol (void);
  17. Prototype void do_wleft (void);
  18. Prototype void do_wright (void);
  19. Prototype void do_split (void);
  20. Prototype int do_join (void);
  21. Prototype void do_margin (void);
  22. Prototype void do_wordwrap (void);
  23. Prototype void do_setparcol (void);
  24. Prototype void do_reformat (int);
  25. Prototype void do_tabstop (void);
  26. Prototype void do_insertmode (void);
  27. Prototype void do_insline (void);
  28. Prototype void do_deline (void);
  29. Prototype void do_chfilename (void);
  30. Prototype void do_edit (void);
  31. Prototype void do_bsave (void);
  32. Prototype void do_save (void);
  33. Prototype void do_saveas (void);
  34. Prototype void do_savetabs (void);
  35. Prototype void do_block (void);
  36. Prototype int blockok (void);
  37. Prototype void do_bdelete (void);
  38. Prototype void do_bcopy (void);
  39. Prototype void do_bmove (void);
  40. Prototype void do_if (void);
  41. Prototype int do_toggle (int);
  42. Prototype void do_tlate (void);
  43. Prototype void do_bsource (void);
  44. Prototype void do_scanf (void);
  45. Prototype void do_bappend(void);
  46. Prototype void do_append(void);
  47. Prototype int extend (struct _ED *, int);
  48. Prototype int makeroom (int);
  49. Prototype void freelist (char **, int);
  50.  
  51. typedef struct DiskObject   DISKOBJ;
  52.  
  53. #define nomemory()  {memoryfail = 1;}
  54.  
  55. extern char MForceTitle;
  56. extern void do_bmove();
  57.  
  58. ED *
  59. uninit_init(ep)
  60. ED *ep;
  61. {
  62.     FONT  *font;
  63.     BPTR lock = DupLock((BPTR)ep->dirlock);
  64.     WIN *win;
  65.     int bufsiz = offsetof(struct _ED,EndConfig) - offsetof(struct _ED, BeginConfig);
  66.     char *buf = malloc(bufsiz);
  67.  
  68.     movmem(&ep->BeginConfig, buf, bufsiz);
  69.     win = ep->Win;
  70.     font = ep->Font;
  71.     ep->Font = NULL;
  72.     text_uninit();
  73.     text_init(Ep, NULL, NULL);
  74.     ep = Ep;
  75.     if (ep->Font)
  76.     CloseFont(ep->Font);
  77.     ep->Win = win;
  78.     ep->Font = font;
  79.  
  80.     movmem(buf, &ep->BeginConfig, bufsiz);
  81.  
  82.     ep->Modified = 0;
  83.     ep->Line = ep->Topline = 0;
  84.     UnLock((BPTR)ep->dirlock);
  85.     ep->dirlock = (long)lock;
  86.  
  87.     free(buf);
  88.     return(ep);
  89. }
  90.  
  91. void
  92. do_remeol()
  93. {
  94.     Current[Clen = Ep->Column] = 0;
  95.     text_sync();
  96.     text_redisplaycurrline();
  97. }
  98.  
  99. void
  100. do_wleft()
  101. {
  102.     ED *ep = Ep;
  103.     int i;
  104.  
  105.     for (;;) {
  106.     i = ep->Column;
  107.     if (i == 0)
  108.         goto prevline;
  109.     --i;
  110.     while (i && Current[i] == ' ')
  111.         --i;
  112.     if (i == 0 && Current[0] == ' ') {
  113. prevline:
  114.         if (Comlinemode || ep->Line == 0) {
  115.         i = ep->Column;
  116.         break;
  117.         }
  118.         text_sync();
  119.         --ep->Line;
  120.         text_load();
  121.         ep->Column = Clen;
  122.         continue;
  123.     }
  124.     while (i && Current[i] != ' ')
  125.         --i;
  126.     if (Current[i] == ' ')
  127.         ++i;
  128.     break;
  129.     }
  130.     ep->Column = i;
  131.     text_sync();
  132. }
  133.  
  134. void
  135. do_wright()
  136. {
  137.     ED *ep = Ep;
  138.     int i;
  139.  
  140.     for (;;) {
  141.     i = ep->Column;
  142.     if (i == Clen)
  143.         goto nextline;
  144.     while (i != Clen && Current[i] != ' ')  /* skip past current word */
  145.         ++i;
  146.     while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  147.         ++i;
  148.     if (i == Clen) {
  149. nextline:
  150.         if (Comlinemode || ep->Line == ep->Lines - 1) {
  151.         i = ep->Column;
  152.         break;
  153.         }
  154.         text_sync();
  155.         ++ep->Line;
  156.         text_load();
  157.         ep->Column = i = 0;
  158.         if (Current[0] != ' ')
  159.         break;
  160.         continue;
  161.     }
  162.     break;
  163.     }
  164.     ep->Column = i;
  165.     text_sync();
  166. }
  167.  
  168. void
  169. do_split()        /* split line in two at cursor pos */
  170. {
  171.     ubyte buf[256];
  172.     ED *ep = Ep;
  173.     RP *rp = ep->Win->RPort;
  174.     char onLastLine;
  175.  
  176.     strcpy(buf, Current+ep->Column);
  177.     Current[Clen = ep->Column] = '\0';
  178.     text_sync();
  179.     SetAPen(rp, ep->BGPen);
  180.     if (Nsu == 0)
  181.     RectFill(rp, COL(0), ROW(ep->Line-ep->Topline), Xbase+Xpixs-1, ROW(ep->Line-ep->Topline+1)-1);
  182.     SetAPen(rp, ep->FGPen);
  183.     text_displayseg(ep->Line - ep->Topline, 1);
  184.  
  185.     onLastLine = (ep->Line == ep->Lines-1);
  186.  
  187.     do_downadd();
  188.     if (!onLastLine)
  189.     do_insline();
  190.     strcpy(Current, buf);
  191.     Clen = strlen(Current);
  192.     text_sync();
  193.     text_displayseg(ep->Line - ep->Topline, 1);
  194.     do_up();
  195. }
  196.  
  197. do_join()
  198. {
  199.     int i = Clen, j;
  200.     ED *ep = Ep;
  201.  
  202.     if (ep->Line + 1 < ep->Lines && strlen(ep->List[ep->Line+1])+i <= 253) {
  203.     if (i && Current[i-1] != ' ')
  204.         Current[i++] = ' ';
  205.     strcpy(Current+i, ep->List[ep->Line+1]);
  206.     for (j = i; Current[j] == ' '; ++j);
  207.     for (; i >= 0 && Current[i] == ' '; --i);
  208.     if (j > i+2)
  209.         movmem(Current+j, Current+i+2, strlen(Current+j)+1);
  210.     Clen = strlen(Current);
  211.     text_sync();
  212.     text_displayseg(ep->Line - ep->Topline, 1);
  213.     {
  214.         int l = text_lineno();
  215.         do_down();
  216.         do_deline();
  217.         if (l != text_lineno())
  218.         do_up();
  219.     }
  220.     return(1);
  221.     }
  222.     return(0);
  223. }
  224.  
  225. void
  226. do_margin()
  227. {
  228.     Ep->Margin = atoi(av[1]);
  229. }
  230.  
  231. void
  232. do_wordwrap()
  233. {
  234.     ED *ep = Ep;
  235.  
  236.     if (av[1][1] == 'n')
  237.     ep->Wordwrap = 1;
  238.     if (av[1][1] == 'f')
  239.     ep->Wordwrap = 0;
  240.     if (av[1][0] == 't')
  241.     ep->Wordwrap = 1 - ep->Wordwrap;
  242.     if (ep->Wordwrap)
  243.     title("Wordwrap ON");
  244.     else
  245.     title("Wordwrap OFF");
  246. }
  247.  
  248. void
  249. do_setparcol()
  250. {
  251.     Ep->WWCol = atoi(av[1]);
  252. }
  253.  
  254. /*
  255.  * n == -1  :    force reformat entire paragraph
  256.  * n ==  0  :    only until line equalizes (from text_write())
  257.  *
  258.  * What is a paragraph?   A paragraph ends whenever the left justification
  259.  * gets larger, or on a blank line.
  260.  */
  261.  
  262. void
  263. do_reformat(n)
  264. {
  265.     char *str;
  266.     ED *ep = Ep;
  267.     RP *rp = ep->Win->RPort;
  268.     int nlok, lnsc, fnst, fnsc;
  269.     int column = ep->Column;
  270.     int srow   = ep->Line;
  271.     int crow   = srow;
  272.     int erow   = srow;
  273.     short dins = 0;        /* relative insert lines/delete lines   */
  274.     char moded = 0;        /* any modifications done at all?        */
  275.     char checked = 0;        /* for cursor positioning.            */
  276.  
  277.     if (ep->Margin == 0)
  278.     ep->Margin = 75;
  279.  
  280.     ++Nsu;
  281.     for (;;) {
  282.     str = (char *)ep->List[ep->Line+1];
  283.     fnst = 0;
  284.     fnsc = firstns(Current);
  285.     nlok = (ep->Line + 1 < ep->Lines && fnsc >= (fnst=firstns(str)));
  286.     if (ep->WWCol >= 0)
  287.         fnst = fnsc = ep->WWCol;
  288.     if (nlok && str[0] == 0)
  289.         nlok = 0;
  290.     lnsc = lastns(Current);
  291.     if (lnsc < ep->Margin) {    /* space at end of line for marg-lnsc-2 letter word   */
  292.         if (nlok == 0)      /* but no more data to joinup   */
  293.         break;          /* done */
  294.         if (ep->Margin - lnsc - 2 >= wordlen(str+fnst)) {
  295.         ep->Column = 0;
  296.         Clen = lastns(Current);
  297.         if (Current[Clen])
  298.             ++Clen;
  299.         moded = 1;
  300.         --dins;
  301.         if (do_join())
  302.             continue;
  303.         ++dins;
  304.         title("Error, Margin > 124");
  305.         break;
  306.         }
  307.         if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  308.         break;
  309.         do_down();
  310.         erow = ep->Line;
  311.         continue;
  312.     }
  313.                 /* no space, need to split    */
  314.                 /* find start of prev word    */
  315.     for (;;) {
  316.         int i = lnsc;
  317.         while (i && Current[i] != ' ')
  318.         --i;
  319.         lnsc = i;
  320.         if (i >= ep->Margin) {
  321.         while (i && Current[i] == ' ')
  322.             --i;
  323.         if (i < ep->Margin)
  324.             break;
  325.         lnsc = i;
  326.         continue;
  327.         }
  328.         break;
  329.     }
  330.     if (lnsc) {        /* ok to split at word        */
  331.         ++lnsc;
  332.         ++dins;
  333.         ep->Column = lnsc;
  334.         do_split(); /* Split at point LNSC        */
  335.         do_down();        /* must insert proper amount?    */
  336.         {
  337.         int indent = (nlok == 0) ? fnsc : fnst;
  338.         if (ep->WWCol >= 0)
  339.             indent = ep->WWCol;
  340.         if (!checked) {
  341.             checked = 1;
  342.             if (lnsc <= column) {   /* if split before cursor    */
  343.             column = column - ep->Column + indent;
  344.             ++crow;
  345.             }
  346.         }
  347.         if (Clen + indent < 253) {
  348.             movmem(Current, Current + indent, strlen(Current)+1);
  349.             setmem(Current, indent, ' ');
  350.             Clen += indent;
  351.         }
  352.         }
  353.         erow = ep->Line;
  354.         continue;
  355.     }
  356.     if (n == 0)
  357.         break;
  358.     do_down();
  359.     }
  360.     if (column < 0 || column > 200)
  361.     column = 0;
  362.     if (srow >= ep->Lines) {
  363.     srow = ep->Lines - 1;
  364.     goto ra;
  365.     }
  366.     if (dins || srow < ep->Topline || srow >= ep->Topline + Rows) {
  367. ra:
  368.     text_sync();
  369.     --Nsu;
  370.     ep->Line = crow;
  371.     ep->Column = column;
  372.     text_load();
  373.     if (!text_sync())
  374.         text_redisplay();
  375.     } else {
  376.     text_sync();
  377.     --Nsu;
  378.     ep->Line = crow;
  379.     ep->Column = column;
  380.     text_load();
  381.     if (erow != srow) {
  382.         if (!text_sync()) {
  383.         ++erow;
  384.         if (erow - ep->Topline > Rows)
  385.             erow = ep->Topline + Rows;
  386.         SetAPen(rp, ep->BGPen);
  387.         RectFill(rp, COL(0), ROW(srow - ep->Topline), Xbase+Xpixs-1, ROW(erow - ep->Topline)-1);
  388.         SetAPen(rp, ep->FGPen);
  389.         text_displayseg(srow - ep->Topline, erow - srow);
  390.         }
  391.     } else {
  392.         text_sync();
  393.         if (moded)
  394.         text_redisplaycurrline();
  395.     }
  396.     }
  397.     if (column > Clen) {
  398.     setmem(Current+Clen, column - Clen, ' ');
  399.     Current[column] = 0;
  400.     }
  401.     ep->Column = column;
  402. }
  403.  
  404. void
  405. do_tabstop()
  406. {
  407.     Ep->Tabstop = atoi(av[1]);
  408. }
  409.  
  410. void
  411. do_insertmode()
  412. {
  413.     ED *ep = Ep;
  414.  
  415.     if (av[1][0]) {
  416.     switch(av[1][1] & 0x1F) {
  417.     case 'n'&0x1F:
  418.         ep->Insertmode = 1;
  419.         break;
  420.     case 'f'&0x1F:
  421.         ep->Insertmode = 0;
  422.         break;
  423.     case 'o'&0x1F:
  424.         ep->Insertmode = 1 - ep->Insertmode;
  425.         break;
  426.     }
  427.     if (ep->Insertmode)
  428.         title("Insert mode on");
  429.     else
  430.         title("Insert mode off");
  431.     }
  432. }
  433.  
  434. void
  435. do_insline()
  436. {
  437.     ubyte *ptr;
  438.     ED *ep = Ep;
  439.     RP *rp = ep->Win->RPort;
  440.  
  441.     ep->Modified = 1;
  442.     text_sync();
  443.     if (makeroom(32) && (ptr = allocb(1))) {
  444.     bmovl(ep->List+ep->Line, ep->List+ep->Line+1,ep->Lines-ep->Line);
  445.     ep->List[ep->Line] = ptr;
  446.     *ptr = 0;
  447.     ++ep->Lines;
  448.     if (BEp == ep) {
  449.         if (ep->Line < BSline)
  450.         ++BSline;
  451.         if (ep->Line <= BEline)
  452.         ++BEline;
  453.     }
  454.     } else {
  455.     nomemory();
  456.     }
  457.     text_load();
  458.     if (Nsu == 0)
  459.     ScrollRaster(rp,0,-Ysize, COL(0), ROW(ep->Line-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  460.     text_displayseg(ep->Line - ep->Topline, 1);
  461. }
  462.  
  463. void
  464. do_deline()
  465. {
  466.     int delline;
  467.     ED *ep = Ep;
  468.     RP *rp = ep->Win->RPort;
  469.  
  470.     strcpy(Deline, Current);
  471.     if (ep->Lines > 1) {
  472.     ep->Modified = 1;
  473.     text_sync();
  474.  
  475.     FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  476.     bmovl(ep->List+ep->Line+1, ep->List+ep->Line,ep->Lines-ep->Line-1);
  477.     if (BEp == ep) {
  478.         if (ep->Line < BSline)
  479.         --BSline;
  480.         if (ep->Line <= BEline)
  481.         --BEline;
  482.     }
  483.     delline = ep->Line;
  484.     if (ep->Line >= --ep->Lines) {
  485.         --ep->Line;
  486.         text_load();
  487.         if (ep->Line < ep->Topline) {
  488.         if (Nsu == 0) {
  489.             ep->Topline = ep->Line - (Rows>>1);
  490.             if (ep->Topline < 0)
  491.             ep->Topline = 0;
  492.             text_redisplay();
  493.         }
  494.         return;
  495.         }
  496.     }
  497.     text_load();
  498.     if (Nsu == 0)
  499.         ScrollRaster(rp,0,Ysize, COL(0), ROW(delline-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  500.     text_displayseg(Rows-1, 1);
  501.     } else {
  502.     do_firstcolumn();
  503.     do_remeol();
  504.     ep->Modified = 0;
  505.     }
  506. }
  507.  
  508. void
  509. do_chfilename()
  510. {
  511.     text_sync();
  512.     strncpy(Ep->Name, av[1], 63);
  513.     MForceTitle = 1;
  514. }
  515.  
  516. void
  517. do_edit()
  518. {
  519.     FILE *fi;
  520.     BPTR oldlock;
  521.     long lines;
  522.     ubyte buf[256];
  523.     ubyte *ptr;
  524.     char failed = 1;
  525.     ED *ep = Ep;
  526.  
  527.     text_sync();
  528.     if (*av[0] == 'n') {        /* newfile or insfile   */
  529.     if (ep->Modified && getyn("Delete modified Image?") == 0)
  530.         return;
  531.     ep = uninit_init(ep);
  532.     strncpy(ep->Name, av[1], 63);
  533.     } else {
  534.     ep->Modified = 1;
  535.     }
  536.     lines = ep->Lines;
  537.     oldlock = CurrentDir((BPTR)ep->dirlock);
  538.     if (fi = fopen(av[1], "r")) {
  539.     int len;
  540.     char oktitle = 1;
  541.  
  542.     title("Loading...");
  543.     while ((len = xefgets(fi, buf, 255)) >= 0) {
  544.         failed = 0;
  545.         if (makeroom(256) && (ptr = allocb(len+1))) {
  546.         ep->List[ep->Lines++] = ptr;
  547.         movmem(buf, ptr, len+1);
  548.         } else {
  549.         set_window_params();
  550.         nomemory();
  551.         oktitle = 0;
  552.         break;
  553.         }
  554.     }
  555.     set_window_params();
  556.     if (oktitle)
  557.         title("OK");
  558.     } else {
  559.     title("File Not Found");
  560. #if AREXX
  561.     CmdErr = 5;
  562. #endif
  563.     }
  564.     if (fi)
  565.     fclose(fi);
  566.     CurrentDir(oldlock);
  567.     if (ep->Lines != 1 && lines == 1 && ep->List[0][0] == 0) {
  568.     ep->Modified = 0;
  569.     ep->Line = 0;
  570.     FreeMem(ep->List[0], strlen(ep->List[0])+1);
  571.     bmovl(ep->List+1, ep->List,--ep->Lines);
  572.     } else {
  573.     if (!failed && lines <= ep->Lines - 1) {
  574.         long bsline, beline;
  575.         short bschar, bechar;
  576.         ED *bep = BEp;
  577.  
  578.         bsline = BSline;
  579.         beline = BEline;
  580.         bschar = BSchar;
  581.         bechar = BEchar;
  582.  
  583.         BEp = ep;
  584.         BSline = lines;
  585.         BEline = ep->Lines - 1;
  586.         do_bmove();
  587.  
  588.         if (bep && bep != ep) {
  589.         BSline = bsline;
  590.         BEline = beline;
  591.         bschar = BSchar;
  592.         bechar = BEchar;
  593.         BEp = bep;
  594.         }
  595.     }
  596.     }
  597.     set_window_params();
  598.     text_load();
  599.     text_redisplay();
  600. }
  601.  
  602.  
  603. static char blockmode;
  604. static char *openmode = "w";
  605.  
  606. void
  607. do_bappend()
  608. {
  609.     char *oldMode = openmode;
  610.  
  611.     blockmode = 1;
  612.     openmode = "a";
  613.     do_saveas();
  614.     openmode = oldMode;
  615. }
  616.  
  617. void
  618. do_append()
  619. {
  620.     char *oldMode = openmode;
  621.  
  622.     openmode = "a";
  623.     do_saveas();
  624.     openmode = oldMode;
  625. }
  626.  
  627. void
  628. do_bsave()
  629. {
  630.     blockmode = 1;
  631.     do_saveas();
  632. }
  633.  
  634. void
  635. do_save()
  636. {
  637.     av[1] = Ep->Name;
  638.     do_saveas();
  639. }
  640.  
  641. void
  642. do_savetabs()
  643. {
  644.     Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
  645. }
  646.  
  647. void
  648. do_saveas()
  649. {
  650.     BPTR oldlock;
  651.     FILE *fi;
  652.     long i;
  653.     short j, k;
  654.     ubyte *ptr, *bp;
  655.     long xs, xe;
  656.     ubyte buf[256];
  657.     char bm;
  658.     ED *ep;
  659.  
  660.     bm = blockmode;
  661.     if (blockmode && blockok()) {
  662.     xs = BSline;
  663.     xe = BEline + 1;
  664.     ep = BEp;
  665.     } else {
  666.     xs = 0;
  667.     xe = Ep->Lines;
  668.     ep = Ep;
  669.     }
  670.     blockmode = 0;
  671.     text_sync();
  672.     oldlock = CurrentDir((BPTR)Ep->dirlock);
  673.     if (IconSaveOpt && IconBase) {    /* Write out .info file */
  674.     DISKOBJ sdo, *d;
  675.     clrmem(&sdo, sizeof(sdo));
  676.     if ((d = GetDiskObject(av[1])) == NULL) {
  677.         if (Wbs == NULL || getpathto(Wbs->sm_ArgList[0].wa_Lock, Wbs->sm_ArgList[0].wa_Name, buf) == 0)
  678.         strcpy(buf, "DME");
  679.         sdo.do_Magic = WB_DISKMAGIC;
  680.         sdo.do_Version = WB_DISKVERSION;
  681.         makemygadget(&sdo.do_Gadget);
  682.         sdo.do_Type = WBPROJECT;
  683.         sdo.do_DefaultTool = (char *)buf;
  684.         sdo.do_ToolTypes = NULL;
  685.         sdo.do_CurrentX = NO_ICON_POSITION;
  686.         sdo.do_CurrentY = NO_ICON_POSITION;
  687.         sdo.do_DrawerData = NULL;
  688.         sdo.do_ToolWindow = NULL;
  689.         sdo.do_StackSize = 8192;
  690.         PutDiskObject(av[1], &sdo);
  691.     } else {
  692.         FreeDiskObject(d);
  693.     }
  694.     }
  695.     if (fi = fopen(av[1], openmode)) {
  696.     if (openmode[0] == 'a')
  697.         title("Appending...");
  698.     else
  699.         title("Saving...");
  700.     for (i = xs; i < xe; ++i) {
  701.         ptr = ep->List[i];
  702.         if (Savetabs) {
  703.         for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  704.             *bp = *ptr;
  705.             if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  706.             k = j;
  707.             while (k-- >= 0 && *bp == ' ')
  708.                 --bp;
  709.             *++bp = 9;
  710.             } else {
  711. #ifdef NOTDEF
  712.             if (*bp < 32 || *bp == '\"' || *bp == '\'' || *bp == '\`' || *bp == '(')
  713.                 break;
  714. #else
  715.             if (*bp < 32 || *bp == '\"' || *bp == '\'' || *bp == '\`')
  716.                 break;
  717. #endif
  718.             }
  719.         }
  720.         strcpy(bp, ptr);
  721.         ptr = buf;
  722.         }
  723.         fputs(ptr, fi);
  724.         fputc('\n', fi);
  725.     }
  726.     if (fclose(fi)) {
  727. err:        Abortcommand = 1;
  728.         title("WRITE FAILED!");
  729.     } else {
  730.         ep->Modified &= bm;
  731.         title("OK");
  732.     }
  733.     } else {
  734.     title("Unable to open write file");
  735.     Abortcommand = 1;
  736.     }
  737.     CurrentDir(oldlock);
  738. }
  739.  
  740. void
  741. do_block()        /* block, unblock    */
  742. {
  743.     text_sync();
  744.  
  745.     switch(av[0][0]) {
  746.     case 'b':
  747.     if (BSline < 0) {
  748. bstart:
  749.         BEp = Ep;
  750.         BSline = Ep->Line;
  751.         title("Block Begin");
  752.     } else {
  753.         if (BEline > -1) {
  754.         title("Block Already Marked");
  755.         break;
  756.         }
  757.         if (BEp != Ep)
  758.         goto bstart;
  759.         title("Block End");
  760.         BEline = Ep->Line;
  761.         if (BSline > BEline) {
  762.         BEline = BSline;
  763.         BSline = Ep->Line;
  764.         }
  765.         text_redrawblock(1);
  766.     }
  767.     break;
  768.     case 'u':
  769.     text_redrawblock(0);
  770.     title ("Block Unmarked");
  771.     break;
  772.     }
  773. }
  774.  
  775.  
  776. blockok()
  777. {
  778.     if (BEp && BSline >= 0 && BSline <= BEline && BEline < BEp->Lines)
  779.     return(1);
  780.     BEp = NULL;
  781.     BSline = BEline = -1;
  782.     title("Block Not Specified");
  783.     return(0);
  784. }
  785.  
  786. void
  787. do_bdelete()
  788. {
  789.     long n;
  790.     ED *bep = BEp;
  791.     WIN *savewin = Ep->Win;
  792.  
  793.     if (blockok()) {
  794.     text_switch(bep->Win);
  795.     n = BEline - BSline + 1;
  796.     if (bep->Line >= BSline && bep->Line <= BEline)
  797.         bep->Line = BSline;
  798.     if (bep->Line > BEline)
  799.         bep->Line -= n;
  800.     freelist(bep->List + BSline, BEline - BSline + 1);
  801.     bmovl(bep->List+BEline+1,bep->List+BSline,(bep->Lines-BEline-1));
  802.     bep->Lines -= n;
  803.     bep->Modified = 1;
  804.     if (bep->Line >= bep->Lines)
  805.         bep->Line = bep->Lines - 1;
  806.     if (bep->Line < 0)
  807.         bep->Line = 0;
  808.     if (bep->Lines == 0) {
  809.         ++bep->Lines;
  810.         bep->List[0] = allocb(1);
  811.         bep->List[0][0] = 0;
  812.     }
  813.     text_load();
  814.     BEp = NULL;
  815.     BSline = BEline = -1;
  816.     if (!text_sync())
  817.         text_redisplay();
  818.     text_switch(savewin);
  819.     }
  820. }
  821.  
  822. void
  823. do_bcopy()
  824. {
  825.     ubyte **list;
  826.     long lines, i;
  827.     ED *ep = Ep;
  828.  
  829.     text_sync();
  830.     if (!blockok())
  831.     return;
  832.     if (ep == BEp && ep->Line > BSline && ep->Line <= BEline) {
  833.     title("Cannot Move into self");
  834.     return;
  835.     }
  836.     lines = BEline - BSline + 1;
  837.     if (extend(ep, lines)) {
  838.     if (list = (ubyte **)allocl(lines)) {
  839.         bmovl(BEp->List+BSline,list,lines);
  840.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  841.         for (i = 0; i < lines; ++i) {
  842.         ubyte *str = allocb(strlen(list[i])+1);
  843.         if (!str) {
  844.             nomemory();
  845.             FreeMem(list, lines * sizeof(char *));
  846.             freelist(ep->List + Ep->Line, i);
  847.             bmovl(ep->List+ep->Line+lines, ep->List+ep->Line, ep->Lines-ep->Line);
  848.             return;
  849.         }
  850.         strcpy(str, list[i]);
  851.         ep->List[ep->Line+i] = str;
  852.         }
  853.         FreeMem(list, lines * sizeof(char *));
  854.     }
  855.     }
  856.     if (ep == BEp && ep->Line <= BSline) {
  857.     BSline += lines;
  858.     BEline += lines;
  859.     }
  860.     ep->Modified = 1;
  861.     ep->Lines += lines;
  862.     text_load();
  863.     if (!text_sync())
  864.     text_redisplay();
  865. }
  866.  
  867.  
  868. void
  869. do_bmove()
  870. {
  871.     long lines;
  872.     ubyte **list;
  873.     ED *ep = Ep;
  874.  
  875.     text_sync();
  876.     if (!blockok())
  877.     return;
  878.     if (BEp == ep && ep->Line >= BSline && ep->Line <= BEline) {
  879.     title("Cannot Move into self");
  880.     return;
  881.     }
  882.     lines = BEline - BSline + 1;
  883.     if (!(list = (ubyte **)allocl(lines))) {
  884.     nomemory();
  885.     return;
  886.     }
  887.     BEp->Modified = ep->Modified = 1;
  888.     bmovl(BEp->List + BSline, list, lines);
  889.     if (ep == BEp) {
  890.     if (ep->Line > BSline) {
  891.         bmovl(ep->List+BEline+1, ep->List+BSline, ep->Line-BEline-1);
  892.         bmovl(list, ep->List + ep->Line - lines, lines);
  893.     } else {
  894.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, BSline-ep->Line);
  895.         bmovl(list, ep->List + ep->Line, lines);
  896.     }
  897.     } else {
  898.     WIN *savewin = ep->Win;
  899.     if (extend(ep, lines)) {
  900.         bmovl(BEp->List+BEline+1, BEp->List+BSline, BEp->Lines-BEline-1);
  901.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  902.         bmovl(list, ep->List+ep->Line, lines);
  903.         ep->Lines += lines;
  904.         BEp->Lines -= lines;
  905.         if (BEp->Line >= BSline && BEp->Line <= BEline)
  906.         BEp->Line = BSline - 1;
  907.         if (BEp->Line > BEline)
  908.         BEp->Line -= lines;
  909.         if (BEp->Line < 0)
  910.         BEp->Line = 0;
  911.         BSline = BEline = -1;
  912.         if (BEp->Lines == 0) {
  913.         ubyte *ptr = allocb(1);
  914.         BEp->List[0] = ptr;
  915.         *ptr = 0;
  916.         ++BEp->Lines;
  917.         }
  918.         text_load();
  919.         text_switch(BEp->Win);
  920.         BEp = NULL;
  921.         ep = Ep;
  922.         if (!ep->iconmode) {
  923.         if (!text_sync())
  924.             text_redisplay();
  925.         }
  926.         text_switch(savewin);
  927.         ep = Ep;
  928.     }
  929.     }
  930.     BSline = BEline = -1;
  931.     BEp = NULL;
  932.     FreeMem(list, lines * sizeof(char *));
  933.     ep->Modified = 1;
  934.     text_load();
  935.     if (!text_sync())
  936.     text_redisplay();
  937. }
  938.  
  939.  
  940. /*
  941.  * IF condition trueaction, IFELSE condition trueaction falseaction
  942.  *
  943.  *  condition:    !condition NOT the specified condition.
  944.  *        #       toggle number is SET
  945.  *        top       top of file (on first line)
  946.  *        bot       end of file (on last line)
  947.  *        left       start of line (leftmost column)
  948.  *        right       end of line (nothing but spaces under and to the right)
  949.  *        modified   text has been modified
  950.  *        insert       currently in insert mode
  951.  *        y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  952.  *        x[<=>]#    cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  953.  *                <> means 'not equal'
  954.  *
  955.  *        cl       char under cursor is lower case
  956.  *        cu       char under cursor is upper case
  957.  *        ca       char under cursor is alpha
  958.  *        cn       char under cursor is numeric
  959.  *        cb       char within selected block
  960.  *        c[<=>]#    char under cursor is (combo of <,>,and =) #
  961.  */
  962.  
  963. void
  964. do_if()
  965. {
  966.     char haselse = (av[0][2] == 'e');
  967.     char iswhile = (av[0][0] == 'w');
  968.     char istrue, notop = 0;
  969.     char c, cx, cc;
  970.     ubyte *buf1, *buf2;
  971.     ubyte *ptr;
  972.     ED *ep = Ep;
  973.     int i, cxn, cn;
  974.  
  975.     buf1 = (ubyte *)malloc(256);
  976.     buf2 = (ubyte *)malloc(256);
  977.     if (buf1 == NULL || buf2 == NULL) {
  978.     if (buf1) free(buf1);
  979.     if (buf2) free(buf2);
  980.     title("No Memory!");
  981.     return;
  982.     }
  983.     breakreset();
  984.     ptr = av[1];
  985.     if (*ptr == '!') {
  986.     notop = 1;
  987.     ++ptr;
  988.     }
  989.     c = ptr[0];
  990.     cn= atoi(ptr);
  991.     cx= ptr[1];
  992.     cxn=atoi(ptr+1);
  993.     strcpy(buf1, av[2]);
  994.  
  995. loop:
  996.     istrue = 0;
  997.     i = 0;
  998.     switch(c) {
  999.     case 'x':
  1000.     i = ep->Column + 1;
  1001.     case 'y':
  1002.     if (!i)
  1003.         i = ep->Line + 1;
  1004. conditional:
  1005.     {
  1006.         int j, n;
  1007.         char any = 0;
  1008.  
  1009.         for (j = 1; ptr[j] && (ptr[j]<'0'||ptr[j]>'9'); ++j);
  1010.         n = atoi(ptr+j);
  1011.         for (j = 1; ptr[j]; ++j) {
  1012.         switch(ptr[j]) {
  1013.         case '<':
  1014.             any = 1;
  1015.             if (i < n)
  1016.             istrue = 1;
  1017.             break;
  1018.         case '=':
  1019.             any = 1;
  1020.             if (i == n)
  1021.             istrue = 1;
  1022.             break;
  1023.         case '>':
  1024.             any = 1;
  1025.             if (i > n)
  1026.             istrue = 1;
  1027.             break;
  1028.         }
  1029.         }
  1030.         if (!any && i == n)  /* default is equivalence   */
  1031.         istrue = 1;
  1032.     }
  1033.     break;
  1034.     case 't':
  1035.     istrue = ep->Line == 0;
  1036.     break;
  1037.     case 'b':
  1038.     istrue = ep->Line == ep->Lines-1;
  1039.     break;
  1040.     case 'l':
  1041.     istrue = ep->Column == 0;
  1042.     break;
  1043.     case 'r':
  1044.     istrue = ep->Column == Clen;
  1045.     break;
  1046.     case 'm':
  1047.     text_sync();
  1048.     istrue = ep->Modified != 0;
  1049.     break;
  1050.     case 'e':
  1051.     istrue = Comlinemode != 0;
  1052.     break;
  1053.     case 'i':
  1054.     istrue = ep->Insertmode != 0;
  1055.     break;
  1056.     case 'c':
  1057.     cc = Current[ep->Column];
  1058.     switch(cx) {
  1059.     case 'b':
  1060.         istrue = BEp == ep && ep->Line >= BSline && ep->Line <= BEline;
  1061.         break;
  1062.     case 'l':
  1063.         istrue = cc >= 'a' && cc <= 'z';
  1064.         break;
  1065.     case 'u':
  1066.         istrue = cc >= 'A' && cc <= 'Z';
  1067.         break;
  1068.     case 'a':
  1069.         istrue = (cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')||(cc>='0'&&cc<='9');
  1070.         break;
  1071.     case 'n':
  1072.         istrue = (cc >= '0' && cc <= '9');
  1073.         break;
  1074.     default:        /* c[<=>]#  */
  1075.         i = Current[ep->Column];
  1076.         goto conditional;
  1077.         break;
  1078.     }
  1079.     break;
  1080.     default:
  1081.     if (c >= '0' && c <= '9')
  1082.         istrue = do_toggle(cn) != 0;
  1083.     else
  1084.         title("bad conditional");
  1085.     break;
  1086.     }
  1087.     istrue ^= notop;
  1088.     if (istrue) {
  1089.     strcpy(buf2, buf1);    /* could be executed multiple times */
  1090.     if (do_command(buf2) == 0)
  1091.         goto done;
  1092.     if (iswhile) {
  1093.         if (breakcheck())
  1094.         Abortcommand = 1;
  1095.         else
  1096.         goto loop;
  1097.     }
  1098.     } else {
  1099.     if (haselse) {        /* only executed once */
  1100.         strcpy(buf2, av[3]);
  1101.         do_command(buf2);
  1102.     }
  1103.     }
  1104. done:
  1105.     free(buf1);
  1106.     free(buf2);
  1107. }
  1108.  
  1109.  
  1110. /*
  1111.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  1112.  */
  1113.  
  1114. do_toggle(n)
  1115. {
  1116.     static char tg[MAXTOGGLE];
  1117.     int i;
  1118.  
  1119.     if (n >= 0) {
  1120.     if (n >= MAXTOGGLE)
  1121.         return(0);
  1122.     return((int)tg[n]);
  1123.     }
  1124.     i = atoi(av[1]);
  1125.     if (i >= 0 && i < MAXTOGGLE) {
  1126.     switch(av[0][0]) {
  1127.     case 't':
  1128.         tg[i] = !tg[i];
  1129.         break;
  1130.     case 's':
  1131.         tg[i] = 1;
  1132.         break;
  1133.     case 'r':
  1134.         tg[i] = 0;
  1135.         break;
  1136.     }
  1137.     }
  1138. }
  1139.  
  1140.  
  1141. void
  1142. do_tlate()
  1143. {
  1144.     ubyte *ptr = av[1];
  1145.     ED *ep = Ep;
  1146.     char c = Current[ep->Column];
  1147.  
  1148.     if (c == 0)
  1149.     c = ' ';
  1150.     if (ptr[0] == '+')
  1151.     c += atoi(ptr+1);
  1152.     else
  1153.     if (ptr[0] == '-')
  1154.     c -= atoi(ptr+1);
  1155.     else
  1156.     c = atoi(ptr);
  1157.     if (c) {
  1158.     if (Current[ep->Column] == 0) {
  1159.         Clen = ep->Column + 1;
  1160.         Current[Clen] = 0;
  1161.     }
  1162.     Current[ep->Column] = c;
  1163.     if (Nsu == 0) {
  1164.         movetocursor();
  1165.         setpen(ep->Line);
  1166.         Text(ep->Win->RPort, Current+ep->Column, 1);
  1167.     }
  1168.     }
  1169. }
  1170.  
  1171. /*
  1172.  *  BSOURCE
  1173.  *
  1174.  *  note that since the start and end lines are loaded immediately and the
  1175.  *  block unblock'd before execution starts, you can theoretically have
  1176.  *  another BSOURCE as part of this BSOURCE (but be carefull!).
  1177.  */
  1178.  
  1179. void
  1180. do_bsource()
  1181. {
  1182.     ubyte buf[256];
  1183.     int i, sl, se;
  1184.  
  1185.     if (blockok()) {
  1186.     sl = BSline;
  1187.     se = BEline + 1;
  1188.     for (i = sl; BEp && i < se && i < BEp->Lines; ++i) {
  1189.         text_sync();    /* make sure we are using latest text */
  1190.         strcpy(buf, BEp->List[i]);
  1191.         if (do_command(buf) == 0)
  1192.         break;
  1193.     }
  1194.     text_redrawblock(0);
  1195.     }
  1196. }
  1197.  
  1198. /*
  1199.  *  SCANF controlstring
  1200.  *
  1201.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  1202.  *  control string.
  1203.  */
  1204.  
  1205. void
  1206. do_scanf()
  1207. {
  1208.     char buf[256];
  1209.  
  1210.     buf[0] = 0;
  1211.     sscanf(Current+Ep->Column,av[1],buf,buf,buf,buf,buf,buf,buf);
  1212.     if (String)
  1213.     free(String);
  1214.     String = (char *)malloc(strlen(buf)+1);
  1215.     strcpy(String,buf);
  1216.     title(String);
  1217. }
  1218.  
  1219. void
  1220. movetocursor()
  1221. {
  1222.     ED *ep = Ep;
  1223.     Move(ep->Win->RPort, XTbase+(ep->Column-ep->Topcolumn)*Xsize, YTbase+(ep->Line-ep->Topline)*Ysize);
  1224. }
  1225.  
  1226. extend(ep, lines)
  1227. ED *ep;
  1228. {
  1229.     long extra = ep->Maxlines - ep->Lines;
  1230.     ubyte **list;
  1231.  
  1232.     if (lines > extra) {
  1233.     lines += ep->Lines;
  1234.     if (list = (ubyte **)allocl(lines)) {
  1235.         bmovl(ep->List, list, ep->Lines);
  1236.         FreeMem(ep->List, sizeof(char *) * ep->Maxlines);
  1237.         ep->Maxlines = lines;
  1238.         ep->List = list;
  1239.         return(1);
  1240.     }
  1241.     nomemory();
  1242.     return(0);
  1243.     }
  1244.     return(1);
  1245. }
  1246.  
  1247. makeroom(n)
  1248. {
  1249.     ED *ep = Ep;
  1250.     if (ep->Lines >= ep->Maxlines)
  1251.     return(extend(ep, n));
  1252.     return(1);
  1253. }
  1254.  
  1255. void
  1256. freelist(list, n)
  1257. char **list;
  1258. {
  1259.     while (n) {
  1260.     FreeMem(list[0], strlen(list[0])+1);
  1261.     ++list;
  1262.     --n;
  1263.     }
  1264. }
  1265.  
  1266.